/*----------------------------------------------------------------------------*
 *                                                                            *
 *                              n w - g t p v 2 c                             * 
 *    G P R S   T u n n e l i n g    P r o t o c o l   v 2 c    S t a c k     *
 *                                                                            *
 *                                                                            *
 * Copyright (c) 2010-2011 Amit Chawre                                        *
 * All rights reserved.                                                       *
 *                                                                            *
 * Redistribution and use in source and binary forms, with or without         *
 * modification, are permitted provided that the following conditions         *
 * are met:                                                                   *
 *                                                                            *
 * 1. Redistributions of source code must retain the above copyright          *
 *    notice, this list of conditions and the following disclaimer.           *
 * 2. Redistributions in binary form must reproduce the above copyright       *
 *    notice, this list of conditions and the following disclaimer in the     *
 *    documentation and/or other materials provided with the distribution.    *
 * 3. The name of the author may not be used to endorse or promote products   *
 *    derived from this software without specific prior written permission.   *
 *                                                                            *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR       *
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  *
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.    *
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,           *
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT   *
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  *
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY      *
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT        *
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF   *
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.          *
 *----------------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include "bstrlib.h"

#include "NwTypes.h"
#include "NwLog.h"
#include "NwUtils.h"
#include "NwGtpv2cLog.h"
#include "NwGtpv2c.h"
#include "NwGtpv2cPrivate.h"
#include "NwGtpv2cIe.h"
#include "NwGtpv2cMsg.h"
#include "dynamic_memory_check.h"
#include "log.h"


#ifdef __cplusplus
extern "C" {
#endif


  typedef struct NwGtpv2cMsgIeInfo {
    uint8_t                                 ieType;
    uint8_t                                 ieMinLength;
    uint8_t                                 ieInstance;
    uint8_t                                 iePresence;
    struct NwGtpv2cMsgIeInfo               *pGroupedIeInfo;
  } NwGtpv2cMsgIeInfoT;

  static
  NwGtpv2cMsgIeInfoT                      createSessionReqBearerCtxtTobeCreatedIeInfoTbl[] = {
    {NW_GTPV2C_IE_EBI, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_BEARER_TFT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_THREE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_FOUR, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_LEVEL_QOS, 18, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    //   { NW_GTPV2C_IE_IMSI           ,       0,      NW_GTPV2C_IE_INSTANCE_ZERO  , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      createSessionReqBearerCtxtTobeRemovedIeInfoTbl[] = {
    {NW_GTPV2C_IE_IMSI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      echoRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      createSessionReqIeInfoTbl[] = {
    {NW_GTPV2C_IE_IMSI, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_MSISDN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_MEI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_ULI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RAT_TYPE, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_INDICATION, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_APN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_APN_RESTRICTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_SELECTION_MODE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_PDN_TYPE, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_PAA, 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_AMBR, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_EBI, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PCO, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FQ_CSID, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FQ_CSID, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, createSessionReqBearerCtxtTobeCreatedIeInfoTbl},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, createSessionReqBearerCtxtTobeRemovedIeInfoTbl},
    {NW_GTPV2C_IE_SERVING_NETWORK, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_RECOVERY, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_CHARGING_CHARACTERISTICS, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_LDN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_LDN, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      createBearerReqBearerCtxtTobeCreatedIeInfoTbl[] = {
    {NW_GTPV2C_IE_EBI, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_BEARER_TFT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_THREE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_FOUR, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_LEVEL_QOS, 22, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_CHARGING_ID, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_FLAGS, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PCO, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      createBearerReqIeInfoTbl[] = {
    {NW_GTPV2C_IE_PROCEDURE_TRANSACTION_ID, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_EBI, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_PCO, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, createBearerReqBearerCtxtTobeCreatedIeInfoTbl},
    {NW_GTPV2C_IE_FQ_CSID, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FQ_CSID, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_CHANGE_REPORTING_ACTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_CSG_INFORMATION_REPORTING_ACTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      createBearerRspBearerCtxtTobeCreatedIeInfoTbl[] = {
    {NW_GTPV2C_IE_EBI, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_THREE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_FOUR, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    /* Warning: NW_GTPV2C_IE_FTEID Up to instance 9 */
    {NW_GTPV2C_IE_PCO, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      createBearerRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, createBearerRspBearerCtxtTobeCreatedIeInfoTbl},
    {NW_GTPV2C_IE_RECOVERY, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FQ_CSID, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FQ_CSID, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FQ_CSID, 0, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PCO, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_UE_TIME_ZONE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_ULI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    /*
     * Do not add below this
     */
    {0, 0, 0}
  };


  static
  NwGtpv2cMsgIeInfoT                      modifyBearerReqIeInfoTbl[] = {
    {NW_GTPV2C_IE_MEI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_SERVING_NETWORK, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_ULI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RAT_TYPE, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_INDICATION, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      releaseAccessBearersReqIeInfoTbl[] = {
    {NW_GTPV2C_IE_EBI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_NODE_TYPE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      deleteSessionReqIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_EBI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_ULI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PCO, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      createSessionRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PAA, 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_APN_RESTRICTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PCO, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      modifyBearerRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_PAA, 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_APN_RESTRICTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      releaseAccessBearersRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      deleteSessionRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PCO, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

/* Message sent over s10 interface */
  static
  NwGtpv2cMsgIeInfoT                      identificationReqIeInfoTbl[] = {
    {NW_GTPV2C_IE_GUTI, 6, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_COMPLETE_REQUEST_MESSAGE, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_SERVING_NETWORK, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      identificationRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_IMSI, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_MM_CONTEXT, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      contextReqIeInfoTbl[] = {
    {NW_GTPV2C_IE_IMSI, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_GUTI, 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_ULI, 7, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PTMSI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_COMPLETE_REQUEST_MESSAGE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_UDP_SOURCE_PORT_NUMBER, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RAT_TYPE, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_HOP_COUNTER, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_SERVING_NETWORK, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_LDN, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      contextRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_IMSI, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_MM_CONTEXT, 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PDN_CONNECTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FQDN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_IP_ADDRESS, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_IP_ADDRESS, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RFSP_INDEX, 2, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_RFSP_INDEX, 2, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_UE_TIME_ZONE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_LDN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      contextAckIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      forwardRelocationReqIeInfoTbl[] = {
    {NW_GTPV2C_IE_IMSI, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_PDN_CONNECTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_FQDN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_MM_CONTEXT, 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CONTAINER, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CONTAINER, 1, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_TARGET_IDENTIFICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_IP_ADDRESS, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_IP_ADDRESS, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CONTAINER, 1, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_SOURCE_IDENTIFICATION, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_SELECTED_PLMN_ID, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_RFSP_INDEX, 2, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_RFSP_INDEX, 2, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_CSG_ID, 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_CSG_MEMBERSHIP_INDICATION, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_UE_TIME_ZONE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_LDN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_ADDITIONAL_MM_CTXT_FOR_SRVCC, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_ADDITIONAL_FLAGS_FOR_SRVCC, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_MSISDN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      forwardRelocationRspIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_BEARER_CONTEXT, 0, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CONTAINER, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CONTAINER, 1, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CONTAINER, 1, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_F_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_TWO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_LDN, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      forwardAccessContextNtfIeInfoTbl[] = {
    {NW_GTPV2C_IE_F_CONTAINER, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      forwardAccessContextAckIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      forwardRelocationCompleteNtfIeInfoTbl[] = {
    {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      forwardRelocationCompleteAckIeInfoTbl[] = {
    {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  /** Paging related signaling. */
  static
  NwGtpv2cMsgIeInfoT                      downlinkDataNtfIeInfoTbl[] = {
      {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_EBI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_ARP, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_IMSI, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_FTEID, 9, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_INDICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      downlinkDataNtfAckIeInfoTbl[] = {
      {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
      {NW_GTPV2C_IE_RECOVERY, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_THROTTLING, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_IMSI, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_EPC_TIMER, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_INTEGER_NUMBER, 0, NW_GTPV2C_IE_INSTANCE_ONE, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  static
  NwGtpv2cMsgIeInfoT                      downlinkDataNtfFailIndIeInfoTbl[] = {
      {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
      {NW_GTPV2C_IE_NODE_TYPE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_IMSI, 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
      {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  /** Relocation Cancel Request. */
  static
  NwGtpv2cMsgIeInfoT                      relocationCancelRequestIeInfoTbl[] = {
    {NW_GTPV2C_IE_IMSI, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
    {NW_GTPV2C_IE_F_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

  /** Relocation Cancel Response. */
  static
  NwGtpv2cMsgIeInfoT                      relocationCancelResponseIeInfoTbl[] = {
      {NW_GTPV2C_IE_CAUSE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},
    {NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL, NULL},

    /*
     * Do not add below this
     */
    {0, 0, 0}
  };

/*----------------------------------------------------------------------------*
                       P R I V A T E     F U N C T I O N S
  ----------------------------------------------------------------------------*/

  /*‘nwGtpv2cMsgGroupedIeCount’ defined but not used [-Wunused-function]
   * static uint32_t                         nwGtpv2cMsgGroupedIeCount (
  NwGtpv2cMsgIeInfoT * pMsgIeInfo) {
    uint32_t                                count = 0;
    NwGtpv2cMsgIeInfoT                     *pGroupedIeInfo = pMsgIeInfo;

    while (pGroupedIeInfo++) {
      if (pGroupedIeInfo->ieType == 0) {
        break;
      }

      count++;
    }

    return count;
  }*/

  static nw_rc_t                            nwGtpv2cMsgIeParseInfoUpdate (
  nw_gtpv2c_msg_ie_parse_info_t * thiz,
  NwGtpv2cMsgIeInfoT * pMsgIeInfo) {
    uint32_t                                i,
                                            j;

    for (i = 0; pMsgIeInfo[i].ieType; i++) {
      if (pMsgIeInfo[i].pGroupedIeInfo) {
        nw_gtpv2c_grouped_ie_parse_info_t            *pMsgIeParseInfo;

        NW_GTPV2C_MALLOC (thiz->hStack, sizeof (nw_gtpv2c_grouped_ie_parse_info_t), pMsgIeParseInfo, nw_gtpv2c_grouped_ie_parse_info_t *);
        pMsgIeParseInfo->groupedIeType = pMsgIeInfo[i].ieType;
        pMsgIeParseInfo->hStack = thiz->hStack;

        for (j = 0; pMsgIeInfo[i].pGroupedIeInfo[j].ieType; j++) {
          pMsgIeParseInfo->ieParseInfo[pMsgIeInfo[i].pGroupedIeInfo[j].ieType][pMsgIeInfo[i].pGroupedIeInfo[j].ieInstance].ieMinLength = pMsgIeInfo[i].pGroupedIeInfo[j].ieMinLength;
          pMsgIeParseInfo->ieParseInfo[pMsgIeInfo[i].pGroupedIeInfo[j].ieType][pMsgIeInfo[i].pGroupedIeInfo[j].ieInstance].iePresence = pMsgIeInfo[i].pGroupedIeInfo[j].iePresence;

          if (pMsgIeInfo[i].pGroupedIeInfo[j].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
            pMsgIeParseInfo->mandatoryIeCount++;
        }

        thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].pGroupedIeInfo = pMsgIeParseInfo;
      } else {
        thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].pGroupedIeInfo = NULL;
      }

      thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].iePresence = pMsgIeInfo[i].iePresence;
      thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].ieMinLength = pMsgIeInfo[i].ieMinLength;

      if (pMsgIeInfo[i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
        thiz->mandatoryIeCount++;
    }

    return NW_OK;
  }

  static nw_rc_t                            nwGtpv2cMsgGroupedIeParse (
  NW_IN nw_gtpv2c_grouped_ie_parse_info_t * thiz,
  NW_IN uint8_t ieType,
  NW_IN uint16_t ieLength,
  NW_IN uint8_t ieInstance,
  NW_IN uint8_t * pIeValue) {
    NW_ASSERT (thiz);
    OAILOG_DEBUG (LOG_GTPV2C,  "Received grouped IE %u with instance %u of length %u in msg-type %u!\n", ieType, ieInstance, ieLength, thiz->groupedIeType);
    return NW_OK;
  }

/*----------------------------------------------------------------------------*
                         P U B L I C   F U N C T I O N S
  ----------------------------------------------------------------------------*/

/**
   Constructor
   @return Pointer to the object on success.
*/

  nw_gtpv2c_msg_ie_parse_info_t                *nwGtpv2cMsgIeParseInfoNew (
  nw_gtpv2c_stack_handle_t hStack,
  uint8_t msgType) {
    nw_rc_t                                   rc;
    nw_gtpv2c_msg_ie_parse_info_t                *thiz;

    NW_GTPV2C_MALLOC (hStack, sizeof (nw_gtpv2c_msg_ie_parse_info_t), thiz, nw_gtpv2c_msg_ie_parse_info_t *);

    if (thiz) {
      memset (thiz, 0, sizeof (nw_gtpv2c_msg_ie_parse_info_t));
      thiz->hStack = hStack;
      thiz->msgType = msgType;

      switch (msgType) {
      case NW_GTP_ECHO_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, echoRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_CREATE_SESSION_REQ:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, createSessionReqIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_CREATE_SESSION_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, createSessionRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_DELETE_SESSION_REQ:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, deleteSessionReqIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_DELETE_SESSION_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, deleteSessionRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_MODIFY_BEARER_REQ:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, modifyBearerReqIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_CREATE_BEARER_REQ:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, createBearerReqIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_CREATE_BEARER_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, createBearerRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_MODIFY_BEARER_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, modifyBearerRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_RELEASE_ACCESS_BEARERS_REQ:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, releaseAccessBearersReqIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_RELEASE_ACCESS_BEARERS_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, releaseAccessBearersRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_FORWARD_RELOCATION_REQ:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, forwardRelocationReqIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_FORWARD_RELOCATION_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, forwardRelocationRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_FORWARD_ACCESS_CONTEXT_NTF:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, forwardAccessContextNtfIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_FORWARD_ACCESS_CONTEXT_ACK:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, forwardAccessContextAckIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_FORWARD_RELOCATION_COMPLETE_NTF:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, forwardRelocationCompleteNtfIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_FORWARD_RELOCATION_COMPLETE_ACK:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, forwardRelocationCompleteAckIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_CONTEXT_REQ:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, contextReqIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_CONTEXT_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, contextRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_CONTEXT_ACK:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, contextAckIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_RELOCATION_CANCEL_REQ:{
            rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, relocationCancelRequestIeInfoTbl);
            NW_ASSERT (NW_OK == rc);
          }
          break;

        case NW_GTP_RELOCATION_CANCEL_RSP:{
            rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, relocationCancelResponseIeInfoTbl);
            NW_ASSERT (NW_OK == rc);
          }
          break;

      case NW_GTP_IDENTIFICATION_REQ:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, identificationReqIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      case NW_GTP_IDENTIFICATION_RSP:{
          rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, identificationRspIeInfoTbl);
          NW_ASSERT (NW_OK == rc);
        }
        break;

      /** Paging related downlink data notification. */
      case NW_GTP_DOWNLINK_DATA_NOTIFICATION: {
        rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, downlinkDataNtfIeInfoTbl);
        NW_ASSERT (NW_OK == rc);
      }
      break;

      case NW_GTP_DOWNLINK_DATA_NOTIFICATION_ACK: {
        rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, downlinkDataNtfAckIeInfoTbl);
        NW_ASSERT (NW_OK == rc);
      }
      break;

      case NW_GTP_DOWNLINK_DATA_NOTIFICATION_FAILURE_IND: {
        rc = nwGtpv2cMsgIeParseInfoUpdate (thiz, downlinkDataNtfFailIndIeInfoTbl);
        NW_ASSERT (NW_OK == rc);
      }
      break;

      default:{
          free_wrapper ((void**)&thiz);
          thiz = NULL;
        }
        break;
      }
    }

    return thiz;
  }

/**
   Destructor
   @return NW_OK on success.
*/

  nw_rc_t                                   nwGtpv2cMsgIeParseInfoDelete (
  nw_gtpv2c_msg_ie_parse_info_t * thiz) {
    NW_GTPV2C_FREE (thiz->hStack, thiz);
    return NW_OK;
  }

/**
   Parse message
   @return NW_OK on success.
*/

  nw_rc_t                                   nwGtpv2cMsgIeParse (
  NW_IN nw_gtpv2c_msg_ie_parse_info_t * thiz,
  NW_IN nw_gtpv2c_msg_handle_t hMsg,
  NW_INOUT nw_gtpv2c_error_t * pError) {
    nw_rc_t                                   rc = NW_OK;
    uint16_t                                mandatoryIeCount = 0;
    uint8_t                                *pIeBufStart;
    uint8_t                                *pIeBufEnd;
    uint16_t                                ieType;
    uint16_t                                ieLength;
    uint16_t                                ieInstance;
    nw_gtpv2c_ie_tlv_t                         *pIe;
    nw_gtpv2c_msg_t                           *pMsg = (nw_gtpv2c_msg_t *) hMsg;
    uint8_t                                 flags = *((uint8_t *) (pMsg->msgBuf));

    pIeBufStart = (uint8_t *) (pMsg->msgBuf + (flags & 0x08 ? 12 : 8));
    pIeBufEnd = (uint8_t *) (pMsg->msgBuf + pMsg->msgLen);
    //memset(pMsg->pIe, 0, sizeof(uint8_t*) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM));
    memset (pMsg->isIeValid, (false), sizeof (uint8_t) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM));

    while (pIeBufStart < pIeBufEnd) {
      pIe = (nw_gtpv2c_ie_tlv_t *) pIeBufStart;
      ieType = pIe->t;
      ieLength = ntohs (pIe->l);
      ieInstance = pIe->i & 0x0F;
      NW_ASSERT (NW_GTPV2C_IE_INSTANCE_MAXIMUM >= ieInstance);
      OAILOG_DEBUG (LOG_GTPV2C,  "Received IE %u with instance %u of length %u in msg-type %u!\n", ieType, ieInstance, ieLength, thiz->msgType);

      if (pIeBufStart + 4 + ieLength > pIeBufEnd) {
        OAILOG_ERROR (LOG_GTPV2C, "Invalid length for IE of type %u and instance %u!\n", ieType, ieInstance);
        pError->cause = NW_GTPV2C_CAUSE_INVALID_LENGTH;
        pError->offendingIe.type = ieType;
        pError->offendingIe.instance = ieInstance;
        return NW_FAILURE;
      }

      if ((thiz->ieParseInfo[ieType][ieInstance].iePresence)) {
        if ((ieLength < (thiz->ieParseInfo[ieType][ieInstance].ieMinLength))) {
          if (thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_OPTIONAL) {
            /*
             * Ignore TLV
             */
            pIeBufStart += (ieLength + 4);
            continue;
          } else {
            pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT;
            pError->offendingIe.type = ieType;
            pError->offendingIe.instance = ieInstance;
            OAILOG_ERROR (LOG_GTPV2C, "Mandatory IE of type %u and instance %u incorrect!\n", ieType, ieInstance);
            return NW_FAILURE;
          }
        }

        if (pMsg->isIeValid[ieType][ieInstance] == true) {
          /*
           * If an information element is repeated in a GTP signalling
           * message in which repetition of the information element is
           * not specified, only the contents of the information element
           * appearing first shall be handled and all subsequent repetitions
           * of the information element shall be ignored.
           * TODO: Add handling for IEs for which repetition is allowed.
           */
          pIeBufStart += (ieLength + 4);
          continue;
        }

        pMsg->pIe[ieType][ieInstance] = (uint8_t *) pIeBufStart;
        pMsg->isIeValid[ieType][ieInstance] = true;

        if (thiz->ieParseInfo[ieType][ieInstance].pGroupedIeInfo) {
          /*
           * Parse the grouped IE
           */
          rc = nwGtpv2cMsgGroupedIeParse (thiz->ieParseInfo[ieType][ieInstance].pGroupedIeInfo, ieType, ieLength, ieInstance, ((uint8_t *) pIe) + 4);

          if (rc != NW_OK) {
            pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT;
            pError->offendingIe.type = ieType;
            pError->offendingIe.instance = ieInstance;
            OAILOG_ERROR (LOG_GTPV2C, "Mandatory IE of type %u and instance %u incorrect!\n", ieType, ieInstance);
            return NW_FAILURE;
          }
        }

        if (thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) {
          mandatoryIeCount++;
        }
      } else {
        OAILOG_WARNING (LOG_GTPV2C,  "Unexpected IE %u with instance %u of length %u received in msg %u!\n", ieType, ieInstance, ieLength, thiz->msgType);
      }

      pIeBufStart += (ieLength + 4);
    }

    if ((NW_OK == rc) && (mandatoryIeCount != thiz->mandatoryIeCount)) {
      for (ieType = 0; ieType < NW_GTPV2C_IE_TYPE_MAXIMUM; ieType++) {
        for (ieInstance = 0; ieInstance < NW_GTPV2C_IE_INSTANCE_MAXIMUM; ieInstance++) {
          if (thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) {
            if (pMsg->isIeValid[ieType][ieInstance] == false) {
              OAILOG_ERROR (LOG_GTPV2C, "Mandatory IE of type %u and instance %u missing in msg type %u\n", ieType, ieInstance, pMsg->msgType);
              pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING;
              pError->offendingIe.type = ieType;
              pError->offendingIe.instance = ieInstance;
              return NW_FAILURE;
            }
          }
        }
      }

      OAILOG_CRITICAL (LOG_GTPV2C, "Unknown mandatory IE missing. Msg parser formed incorrectly!\n");
      pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING;
      pError->offendingIe.type = 0;
      pError->offendingIe.instance = 0;
      return NW_FAILURE;
    }

    pError->cause = NW_GTPV2C_CAUSE_REQUEST_ACCEPTED;
    return NW_OK;
  }


#ifdef __cplusplus
}
#endif

/*--------------------------------------------------------------------------*
                            E N D   O F   F I L E
  --------------------------------------------------------------------------*/
